home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / perl / gimpdoc < prev    next >
Encoding:
Text File  |  2000-08-24  |  12.3 KB  |  435 lines

  1. #!/usr/bin/perl
  2.  
  3. use Gimp qw(:consts spawn_options=no-data);
  4. use Getopt::Std;
  5. #use Config '%Config';
  6.  
  7. $VERSION=2.0;
  8.  
  9. getopts('rw:');
  10.  
  11. if (@ARGV<1) {
  12.    my $me = $0;
  13.    $me =~ s,.*[/\\],,;
  14.    print STDERR <<EOF;
  15.  
  16. Usage: $me [-r] [-w dir] function...
  17.  
  18. Options:
  19.      -r      print raw tbl|nroff source.
  20.      -w dir  create html (use prefix dir when writing out files)
  21.  
  22. EOF
  23.    exit(1);
  24. }
  25.  
  26. Gimp::init;
  27.  
  28. for (@ARGV) {
  29.    push @matches, Gimp->procedural_db_query ($_,"","","","","","");
  30. }
  31.  
  32. @matches or die "No matching function found\n";
  33.  
  34. @matches = sort @matches;
  35.  
  36. %pf_type2string = (
  37.          &PDB_INT8        => 'INT8',
  38.          &PDB_INT16        => 'INT16',
  39.          &PDB_INT32        => 'INT32',
  40.          &PDB_FLOAT        => 'FLOAT',
  41.          &PDB_STRING        => 'STRING',
  42.          &PDB_INT8ARRAY        => 'INT8ARRAY',
  43.          &PDB_INT16ARRAY    => 'INT16ARRAY',
  44.          &PDB_INT32ARRAY    => 'INT32ARRAY',
  45.          &PDB_FLOATARRAY    => 'FLOATARRAY',
  46.          &PDB_STRINGARRAY    => 'STRINGARRAY',
  47.          &PDB_COLOR        => 'COLOUR',
  48.          &PDB_IMAGE        => 'IMAGE',
  49.          &PDB_LAYER        => 'LAYER',
  50.          &PDB_CHANNEL        => 'CHANNEL',
  51.          &PDB_DRAWABLE        => 'DRAWABLE',
  52.          &PDB_DISPLAY        => 'DISPLAY',
  53.          &PDB_SELECTION        => 'SELECTION',
  54.          &PDB_PARASITE        => 'PARASITE',
  55.  
  56.          &PDB_STATUS        => 'STATUS',
  57.          &PDB_REGION        => 'REGION',
  58.          &PDB_BOUNDARY        => 'BOUNDARY',
  59.          &PDB_PATH        => 'PATH',
  60. );
  61.  
  62. sub type2str {
  63.   $pf_type2string{$_[0]}
  64.   ? $pf_type2string{$_[0]}
  65.   : "UNKNOWN($_[0])";
  66. }
  67.  
  68. my %plugin_info;
  69.  
  70. #'extension_db_browser' => ARRAY(0x8290e98)
  71. #   0  '<Toolbox>/Xtns/DB Browser'
  72. #   1  undef
  73. #   2  '/usr/app/lib/gimp/1.1/plug-ins/dbbrowser'
  74. #   3  ''
  75. #   4  936739664
  76. sub get_plugininfo {
  77.    eval {
  78.       my ($a, $b, $c, $d, $e, $f) = Gimp->plugins_query("");
  79.       for $i (0..$#$a) {
  80.          $plugin_info{$f->[$i]} = [map $_->[$i], $a, $b, $c, $d, $e];
  81.       }
  82.    }
  83. }
  84.  
  85. sub format_html {
  86.    $created_by = "<br><hr><font size=-1>This page was created by <tt>gimpdoc</tt>, written by ".
  87.                  "<a href=\"mailto:pcg\@goof.com\">Marc Lehmann <pcg\@goof.com></a></font>";
  88.    $nbsp = " ";
  89.    ($b1,$b0)=('<b>','</b>');
  90.    ($sh1,$sh0)=('<dt>',"<dd>");
  91.    ($tt1,$tt0)=('<tt>','</tt>');
  92.    $br = "<br>";
  93.    $theader = <<EOF;
  94. <table><tr align=left><th>TYPE<th>NAME<th>DESCRIPTION
  95. EOF
  96.    $tr = "<tr>";
  97.    $tend = "</table>";
  98.    $body = '<body text="#000000" link="#1010c0" vlink="#101080" alink="#ff0000" bgcolor="#ffffff">';
  99.    $section = sub {
  100.       "<dt>$_[0]<dd>$_[1]";
  101.    };
  102.    $header = <<'EOF';
  103. <html><head><title>Gimp PDB documentation - $name</title>$body
  104. <a href=\"$prev_fun.html\">$prev_fun</a> << <a href=index.html>INDEX</a> >>
  105. <a href=\"$next_fun.html\">$next_fun</a>
  106. <h1><b>$name</b> ($date)</h1>
  107. <dl>
  108. <dt>NAME<dd><b>$name - $blurb</b>
  109. <dt>SYNOPSIS<dd><tt>$vals<b>$name</b>$args</tt>
  110. <dt>DESCRIPTION<dd>$help
  111. EOF
  112.    $trailer = <<'EOF';
  113. <dt>AUTHOR<dd>$author<br>(c)$date $copyright
  114. </dl>
  115. $created_by
  116. </html>
  117. EOF
  118.    *escape = sub {
  119.       $_[0] =~ s/&/&/;
  120.       $_[0] =~ s/</</;
  121.       $_[0] =~ s/>/>/;
  122.  
  123.       # FIX: the following three lines are only required for my m4 macro package.
  124.       $_[0] =~ s/{/_lbr/;
  125.       $_[0] =~ s/}/{}_rbr{}/;
  126.       $_[0] =~ s/_lbr/{}_lbr{}/;
  127.  
  128.       # do a best effort to replace function names by links
  129.       $_[0] =~ s{\b([a-z_]+_[a-z_]+)\b}{
  130.          my $proc = $1;
  131.          if (grep $_ eq $proc, @matches) {
  132.             "<a href=$proc.html>$proc</a>";
  133.          } else {
  134.             $proc;
  135.          }
  136.       }ge;
  137.    };
  138.    *table_line = sub {
  139.       my ($a,$b,$c) = @_;
  140.       for ($a,$b,$c) { escape($_) };
  141.       "<tr><td>$a<td>$b<td>$c";
  142.    };
  143. }
  144.  
  145. sub format_roff {
  146.    $nbsp = "\\ ";
  147.    ($b1,$b0)=("\\fB","\\fR");
  148.    ($sh1,$sh0)=('.SH ',"\n");
  149.    ($tt1,$tt0)=('','');
  150.    $br = "\n.br\n";
  151.    $theader = <<EOF;
  152. .TS H
  153. expand ;
  154. l l l
  155. ___
  156. lw20 lw20 lw60.
  157. TYPE    NAME    DESCRIPTION
  158. EOF
  159.    $tend = "\n.TE\n";
  160.    $section = sub {
  161.       ".SH $_[0]\n$_[1]\n";
  162.    };
  163.    $header = <<'EOF';
  164. .TH \"$name\" \"gimpdoc\" \"$date\" \"$version\"
  165. .SH NAME
  166. \\fB$name\\fR \- $blurb
  167. .SH SYNOPSIS
  168. $vals\\fB$name\\fR$args
  169. .SH DESCRIPTION
  170. $help
  171. EOF
  172.    $trailer = <<'EOF';
  173. .SH AUTHOR
  174. $author
  175. .br
  176. (c)$date $copyright
  177. EOF
  178.    *escape = sub {};
  179.    *table_line = sub {
  180.       join("    ",$_[0]." ",$_[1]." ","T{\n".$_[2]."\nT}")."\n"; 
  181.    }
  182. }
  183.  
  184. format_roff;
  185.  
  186. my $version = "gimp-".Gimp->major_version.".".Gimp->minor_version;
  187. sub gen_va(\@\@) {
  188.    my @vals = @{+shift};
  189.    my @args = @{+shift};
  190.    my($vals,$args);
  191.  
  192.    if (@vals == 0) {
  193.       $vals = "";
  194.    } elsif (@vals == 1) {
  195.       $vals = "$vals[0][1]$nbsp=$nbsp";
  196.    } else {
  197.       $vals = "(".join(",",map $_->[1],@vals).")$nbsp=$nbsp";
  198.    }
  199.  
  200.    if (@args == 0) {
  201.       $args = "";
  202.    } else {
  203.       $args = "$nbsp(".join(",",map $_->[1],@args).")";
  204.    }
  205.  
  206.    ($vals,$args);
  207. }
  208.  
  209. sub isarray {
  210.    return 1 if $_[0] == &PDB_INT8ARRAY;
  211.    return 1 if $_[0] == &PDB_INT16ARRAY;
  212.    return 1 if $_[0] == &PDB_INT32ARRAY;
  213.    return 1 if $_[0] == &PDB_FLOATARRAY;
  214.    return 1 if $_[0] == &PDB_STRINGARRAY;
  215.    return 0;
  216. }
  217.  
  218. sub killcounts(\@) {
  219.    my $a = shift;
  220.    my $roa=0;
  221.    for(local $_=0; $_<$#$a; $_++) {
  222.       if (isarray ($a->[$_+1][0]) && $a->[$_][0] == &PDB_INT32) {
  223.          splice @$a, $_, 1;
  224.          $roa=1;
  225.       }
  226.    }
  227.    $roa;
  228. }
  229.  
  230. sub weight {
  231.    my ($v,$n,$a)=@$_;
  232.    my $w = $#$v + $#$a;
  233.    $w-- if $n =~ s/^\$\w+//;
  234.    $w += 1-1/(1+length $n);
  235.    if ($n =~ / ([A-Z][a-z]+)$/) {
  236.       $w += 1 unless $1 eq ucfirst $a->[0][1];
  237.    }
  238.    $w;
  239. }
  240.     
  241. sub gen_alternatives(\@$\@) {
  242.    my @vals = @{+shift};
  243.    my $name = shift;
  244.    my @args = @{+shift};
  245.    killcounts(@vals); killcounts(@args);
  246.    my @new = [\@vals,$name,\@args];
  247.    my @res;
  248.    do {
  249.       my @prev = @new;
  250.       @new = ();
  251.       for my $alt (@prev) {
  252.          my @vals = @{$alt->[0]};
  253.          my $name = $alt->[1];
  254.          my @args = @{$alt->[2]};
  255.          # try to get rid of array counts
  256.          unless ($name =~ /[$ ]/) {
  257.             for my $class (qw(
  258.                   Gimp Layer Image Drawable Selection Channel Display
  259.                   Palette Plugin Gradients Edit Progress Region Tile
  260.                   PixelRgn GImpDrawable Patterns GimpParasite
  261.                )) {
  262.                my @pre = @{$class."::PREFIXES"};
  263.                prefix:
  264.                for (@pre) {
  265.                   my $n2 = $name;
  266.                   if ($_ && $n2 =~ s/^$_//) {
  267.                      for my $p (@pre) {
  268.                         last if $_ eq $p;
  269.                         last prefix if Gimp::_gimp_procedure_available($p.$n2);
  270.                      }
  271.                      if ($class eq "Drawable" && @args && $args[0][0] == &PDB_DRAWABLE) {
  272.                         push @new, [\@vals,"\$drawable->$n2",[@args[1..$#args]]];
  273.                      } elsif ($class eq "Layer" && @args && $args[0][0] == &PDB_LAYER) {
  274.                         push @new, [\@vals,"\$layer->$n2",[@args[1..$#args]]];
  275.                      } elsif ($class eq "Channel" && @args && $args[0][0] == &PDB_CHANNEL) {
  276.                         push @new, [\@vals,"\$channel->$n2",[@args[1..$#args]]];
  277.                      } elsif ($class eq "Image" && @args && $args[0][0] == &PDB_IMAGE) {
  278.                         push @new, [\@vals,"\$image->$n2",[@args[1..$#args]]];
  279.                      } elsif (@args < 1 or ($args[0][0] != &PDB_IMAGE
  280.                                          && $args[0][0] != &PDB_DRAWABLE
  281.                                          && $args[0][0] != &PDB_CHANNEL
  282.                                          && $args[0][0] != &PDB_LAYER)) {
  283.                         if ($class =~ /Gimp|Gradient|Palette|Edit|Patterns|GimpParasite|PixelRgn/) {
  284.                            push @new, [\@vals,"${class}->$n2",\@args];
  285.                         } else {
  286.                            push @new, [\@vals,"$n2$nbsp$class",\@args];
  287.                         }
  288.                      }
  289.                      last prefix;
  290.                   }
  291.                }
  292.             }
  293.          }
  294.          if (@args && $args[0][0] == &PDB_INT32 && $args[0][1] eq "run_mode") {
  295.             push @new, [\@vals,,$name,[@args[1..$#args]]];
  296.          }
  297.          if (@args>1 && $args[0][0] == &PDB_IMAGE && $args[1][0] == &PDB_DRAWABLE) {
  298.             push @new, [\@vals,,$name,[@args[1..$#args]]];
  299.          }
  300.       }
  301.       push @res, @new;
  302.    } while @new;
  303.    map {
  304.       my($vals,$args)=gen_va(@{$_->[0]},@{$_->[2]});
  305.       "${tt1}$vals${b1}$_->[1]$b0$args$tt0";
  306.    } map $_->[1], sort {
  307.       $a->[0] <=> $b->[0]
  308.    } map [weight($_),$_], @res;
  309. }
  310.  
  311. sub gen_desc {
  312.    my $name = shift;
  313.    my ($blurb, $help, $author, $copyright, $date, $type, $nargs, $nvals) =
  314.       Gimp->procedural_db_proc_info ($name);
  315.    my @args = map [Gimp->procedural_db_proc_arg ($name, $_)],0..($nargs-1);
  316.    my @vals = map [Gimp->procedural_db_proc_val ($name, $_)],0..($nvals-1);
  317.    my $r;
  318.    
  319.    my($vals,$args)=gen_va(@vals,@args);
  320.  
  321.    my($menu_path, $accelerator, $path, $image_types, $mtime) = @{$plugin_info{$name}};
  322.    for ($blurb, $help, $author, $copyright, $date, $menu_path, $accelerator, $path, $image_types) {
  323.       escape($_);
  324.    }
  325.  
  326.    $r = eval "\"$header\"";
  327.  
  328.    $r .= $section->("MENUPATH", $menu_path) if $menu_path;
  329.    $r .= $section->("IMAGETYPES", $image_types) if $image_types;
  330.    $r .= $section->("ACCELERATOR", $accelerator) if $accelerator;
  331.    if ($nargs) {
  332.       $r .= "${sh1}INPUT ARGUMENTS$sh0$theader";
  333.       for (@args) {
  334.          $r .= table_line(type2str($_->[0]),$_->[1],$_->[2]);
  335.       }
  336.       $r .= $tend;
  337.    }
  338.  
  339.    if ($nvals) {
  340.       $r .= "${sh1}RETURN VALUES$sh0$theader";
  341.       for (@vals) {
  342.          $r .= table_line(type2str($_->[0]),$_->[1],$_->[2]);
  343.       }
  344.       $r .= $tend;
  345.    }
  346.    my @alts = gen_alternatives @vals,$name,@args;
  347.    if (@alts) {
  348.       @alts = @alts[0..5] if @alts > 6;
  349.       $r .= "${sh1}SOME SYNTAX ALTERNATIVES$sh0". join($br, @alts). "\n";
  350.    }
  351.    $r .= $section->("INSTALLATION PATH", $path) if $path;
  352.    $r .= eval "\"$trailer\"";
  353.    $r;
  354. }
  355.  
  356. get_plugininfo;
  357.  
  358. if ($opt_w) {
  359.    format_html;
  360.    $|=1;
  361.    use POSIX 'strftime';
  362.    my $today = strftime ("%Y-%m-%d %H:%M:%SZ", gmtime time);
  363.    open HTML,">$opt_w/index.html" or die "Unable to create '$opt_w/index.html': $!\n";
  364.    print "$opt_w/index.html";
  365.    my %done;
  366.    print HTML <<EOF;
  367. <html><head><title>Gimp PDB Documentation, created on $today by gimpdoc</title>$body
  368. <h1>Gimp PDB Documentation</h1>
  369.  
  370. The following pages contain a htmlified version of the <a
  371. href="http://www.gimp.org/"><b>Gimp</b></a> PDB documentation</b>. They
  372. were automatically generated on $today from $version, using the program
  373. <tt>gimpdoc</tt> (part of the $version distribution). If you have any
  374. questions please direct them to <a href=\"mailto:pcg\@goof.com\">Marc
  375. Lehmann <pcg\@goof.com></a>.
  376.  
  377. EOF
  378.    my($listing,$head);
  379.    for $group (qw(
  380.          script-fu- file_ extension_ plug_in_ perl_fu_ gimp_drawable_ gimp_channel_ gimp_layer_ gimp_image_ gimp_
  381.       ),'.') {
  382.       my $some;
  383.       my $glisting;
  384.       for (grep /^$group/, @matches) {
  385.          next if $done{$_};
  386.          $done{$_}++;
  387.          my $blurb = (Gimp->procedural_db_proc_info($_))[0];
  388.          $blurb = substr($blurb,0,47)."..." if length($blurb)>50;
  389.          escape($blurb);
  390.          $some=1;
  391.          $glisting .= "<tr><td><a href=$_.html>$_</a><td>$blurb";
  392.       }
  393.       if ($some) {
  394.          my $xgroup = $group;
  395.          $xgroup =~ y/-_/ /;
  396.          $xgroup =~ s/\b(.)/uc($1)/ge;
  397.          $xgroup = "Ungrouped Functions" if $xgroup eq ".";
  398.          $head = "<h2><a href=\"#$group\">$xgroup</a></h2>".$head;
  399.          $listing = "<h2><a name=\"$group\">$xgroup</a></h2>".
  400.                     "<table><tr align=left><th>Function<th>Description".
  401.                     $glisting.
  402.                     "</table>".
  403.                     $listing;
  404.       }
  405.    }
  406.    print HTML "$head$listing$created_by</html>";
  407.    close HTML;
  408.    print "\n";
  409.    for $_ (0..$#matches) {
  410.       $prev_fun = $matches[$_-1];
  411.       $next_fun = $matches[$_+1-@matches];
  412.       $name = $matches[$_];
  413.       open HTML,">$opt_w/$name.html" or die "Unable to create '$opt_w/$name.html': $!\n";
  414.       print "$opt_w/$name.html";
  415.       print HTML gen_desc($name);
  416.       close HTML;
  417.       print "\n";
  418.    }
  419. } else {
  420.    format_roff;
  421.    $filter = "| tbl | nroff -man | ( '$ENV{PAGER}' 2>/dev/null || less || pg || more )";
  422.    $filter = ">&STDOUT" if $opt_r;
  423.    open PAGER,$filter or die "unable to open pipe to the pager ($filter)\n";
  424.    if(@matches>1) {
  425.       print PAGER ".TH gimpdoc gimpdoc\n.SH MATCHING FUNCTIONS\n",join("\n.br\n",@matches),"\n";
  426.    }
  427.    for $name (@matches) {
  428.       print PAGER gen_desc($name);
  429.    }
  430. }
  431.  
  432. Gimp::end;
  433.  
  434. close PAGER;
  435.